package cn.lg.soar.common.util.reflect;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;

/**
 * 泛型工具
 * @author luguoxiang
 * @date 2022-06-08
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public interface GenericTypeUtils {

    /**
     * 获取集合元素的泛型
     * @param collection
     * @return
     * @param <T>
     */
    static <T>Class<T> getElementClass(Collection<T> collection) {
        for (T t : collection) {
            if (t == null) {
                continue;
            }
            return (Class<T>) t.getClass();
        }
        throw new RuntimeException("无法获取空集合的泛型");
    }

    /**
     * 获取数组元素类型
     * @param array
     * @return
     * @param <T>
     */
    static <T>Class<T> getElementClass(T[] array) {
        return (Class<T>) array.getClass().getComponentType();
    }

    /**
     * 获取泛型
     * @param target 目标类
     * @return
     */
    static Type getGenericType(Class<?> target) {
        return getGenericType(target, 0);
    }

    /**
     * 获取泛型
     * @param target 目标类
     * @param index 泛型索引
     * @return
     */
    static Type getGenericType(Class<?> target, int index) {
        if (target.isArray()) {
            return target.getComponentType();
        }
        if (target.isInterface()) {
            return getInterfacesGenericType(target, index);
        }
        return getSuperclassGenericType(target, index);
    }

    /**
     * 获取泛型列表
     * @param target
     * @return
     */
    static Type[] getGenericTypes(Class<?> target) {
        if (target.isArray()) {
            return new Type[]{target.getComponentType()};
        }
        if (target.isInterface()) {
            return getInterfacesGenericTypes(target);
        }
        return getSuperclassGenericTypes(target);
    }

    /**
     * 获取数组元素的泛型
     * @param target 目标类
     * @return
     */
    static Type getArrayGenericType(Class<?> target) {
        return target.getComponentType();
    }

    /**
     * 获取超类的泛型
     * @param target 目标类
     * @return
     */
    static Type getSuperclassGenericType(Class<?> target) {
        return getSuperclassGenericType(target, 0);
    }

    /**
     * 获取超类的泛型
     * @param target 目标类
     * @param index 泛型索引
     * @return
     */
    static Type getSuperclassGenericType(Class<?> target, int index) {
        Type[] types = getSuperclassGenericTypes(target);
        return types.length == 0 ? null : types[ index ];
    }

    /**
     * 获取超类的泛型
     * @param target
     * @return
     */
    static Type[] getSuperclassGenericTypes(Class<?> target) {
        Type type = target.getGenericSuperclass();
        if (type instanceof ParameterizedType) {
            return ((ParameterizedType) type).getActualTypeArguments();
        }
        return new Type[0];
    }

    /**
     * 获取接口的泛型类型（第一个接口的第一个泛型）
     * @param target 目标类型
     * @return
     */
    static Type getInterfacesGenericType(Class<?> target) {
        return getInterfacesGenericType(target, 0);
    }

    /**
     * 获取接口的泛型类型（第一个接口的泛型）
     * @param target 目标类型
     * @param index 泛型索引
     * @return
     */
    static Type getInterfacesGenericType(Class<?> target, int index) {
        Type[] types = getInterfacesGenericTypes(target);
        return types.length == 0 ? null : types[ index ];
    }

    /**
     * 获取接口的泛型类型数组（第一个接口的泛型）
     * @param target 目标类
     * @return
     */
    static Type[] getInterfacesGenericTypes(Class<?> target) {
        Type[] interfaces = target.getGenericInterfaces();
        if (interfaces.length == 0) {
            return new Type[0];
        }
        Type type = interfaces[0];
        if (type instanceof ParameterizedType) {
            return ((ParameterizedType) type).getActualTypeArguments();
        }
        return new Type[0];
    }

    /**
     * 获取接口的泛型类型（第一个泛型）
     * @param target 目标类型
     * @param interfacesClass 目标接口类
     * @return
     */
    static Type getInterfacesGenericType(Class<?> target, Class<?> interfacesClass) {
        return getInterfacesGenericType(target, interfacesClass, 0);
    }

    /**
     * 获取接口的泛型类型
     * @param target 目标类型
     * @param interfacesClass 目标接口类
     * @param index 泛型索引
     * @return
     */
    static Type getInterfacesGenericType(Class<?> target, Class<?> interfacesClass, int index) {
        Type[] types = getInterfacesGenericTypes(target, interfacesClass);
        return types.length == 0 ? null : types[ index ];
    }

    /**
     * 获取接口的泛型类型数组
     * @param target 目标类
     * @param interfacesClass 目标接口类
     * @return
     */
    static Type[] getInterfacesGenericTypes(Class<?> target, Class<?> interfacesClass) {
        Class<?>[] interfaces = target.getInterfaces();
        for (int i = 0; i < interfaces.length; i++) {
            if (interfacesClass.isAssignableFrom(interfaces[i])) {
                Type[] genericInterfaces = target.getGenericInterfaces();
                Type type = genericInterfaces[i];
                if (type instanceof ParameterizedType) {
                    return ((ParameterizedType) type).getActualTypeArguments();
                }
            }
        }
        return new Type[0];
    }

}
